package com.dq.mybatis.core;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SqlSession {
	private SqlSessionFactory factory;
	private DBHelper db;

	public SqlSession(SqlSessionFactory factory) {
		this.factory = factory;
		db = new DBHelper(factory.getConfig().getDataSourceMap());
	}

	/*查单个对象
	 * @param id
	 * @param obj
	 * @return
	 */
	public <T> T selectOne(String id, Object obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
		//根据用户给定的id，查找对应的汍行语句，即对应的Mapper Info对象
		MapperInfo mapperlnfo = factory.getMapperlnfo(id);
		if (mapperlnfo == null) { //说明没有对应的执行语句
			throw new RuntimeException ("没有您要仇行的" + id + "...");
		}
		//如果有，则甭要获取要执行的语句，然后获取参数类型，然后根据参数名从参数中获取对应的参数值
		String sql = mapperlnfo.getSql();
		String resultType = mapperlnfo.getResultType();
		String parameterType = mapperlnfo.getParameterType();
		List<String> paramNames = mapperlnfo.getParams();

		//根参数名获取参数值
		List<Object> paramValues = this.getParamValues(parameterType, paramNames, obj);
		System.out.println(sql);
		System.out.println(paramValues);

		return null;
	}

	/*
	 * 根据参数名从指定的对象中获取参数值的方法
	 */
	private List<Object> getParamValues(String parameterType, List<String> paramNames, Object obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
		List<Object> list = new ArrayList<Object>() ; //用来存放sql语句中对应占位符？的值
		if (paramNames.isEmpty() || obj == null) {   //说明不需要注值
			return null;
		}

		if ("int".equalsIgnoreCase(parameterType) || "float".equalsIgnoreCase(parameterType)
				|| "double".equalsIgnoreCase(parameterType) || "String".equalsIgnoreCase(parameterType)) {
			list.add(obj);
		} else if ("map".equalsIgnoreCase(parameterType)) {
			Map<String, Object> map = (Map<String, Object>) obj;
			for (String str : paramNames) { //甭要根赌数名的_序来取值
				list.add(map.get(str));
			}
		}else { //如果是一个用户自定偷橡
			Class<?> clazz = Class.forName(parameterType);
			//获取整个类中的getter —>获取整个类中的所有的方法
			Method[] methods =clazz.getDeclaredMethods();;
			Map<String, Method> getters = new HashMap<String, Method>();
			for (Method method : methods) {
				if (method.getName().startsWith("get")) {
					getters.put(method.getName(), method);
				}
			}

			if (getters.isEmpty()){//如果没有提供getter方法，则返回空
				return null;
			}

			String methodName = null;
			for (String name : paramNames) {
				methodName = "get" + name.substring(0,1).toUpperCase() + name.substring(1) ; // 拼接霜要调用的方法的方法名
				list.add (getters.get(methodName).invoke(obj)); // getPid()-> 这个方法是哪个对象的，这个对象紈是用户给定的这个
			}
		}
		return list;
	}


	public <T> List<T> selectList(String id) throws Exception {
		return this.selectList(id, null);
	}

	/*查集合对象
	 *@param id
	 *@param obj
	 *@return
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> selectList(String id, Object obj) throws Exception {
		//根据用户给定的id，查找对应的执行语句，即对应的MapperInfo对象
		MapperInfo mapperInfo = factory.getMapperlnfo(id);
		if (mapperInfo == null) {//说明没有对应的执行语句
			throw new RuntimeException("没有您要执行的"+ id + "...");
		}
		//如果有，则需要获取要执行的sql语句，然后获取参数类型，然后根据参数名从参数中获取对应的参数值
		String sql = mapperInfo.getSql();
		String resultType = mapperInfo.getResultType();
		String parameterType = mapperInfo.getParameterType();
		List<String> paramNames = mapperInfo.getParams();
		//根据参数名获取参数值
		List<Object> paramValues = this.getParamValues(parameterType, paramNames, obj);
		if ("map".equalsIgnoreCase(resultType)) {
			return (List<T>) db.finds(sql, paramValues);
		} else {
			return (List<T>) db.findObject(sql,Class.forName(resultType), paramValues);
		}
	}

	/* 更新操作
	 * @param id
	 * @param obj
	 * @return
	 */
	public int update(String id, Object obj) throws Exception {
		//根据用户给定的id，查找对应的汍行语句，即对应的MapperInfo对象
		MapperInfo mapperInfo = factory.getMapperlnfo(id);
		if (mapperInfo == null) {//说明没有对应的执行语句
			throw new RuntimeException("没有您要执行的"+ id + "...");
		}
		//如果有，则雷要获取要汍行的挪吾句，然后获取参数类型，然后根据参数名从参数中获取对应的参数值
		String sql = mapperInfo.getSql();
		String parameterType = mapperInfo.getParameterType();
		List<String> paramNames = mapperInfo.getParams();
		//根据参数名获取参数值
		List<Object> paramValues = this.getParamValues(parameterType, paramNames, obj);
		return db.update(sql,paramValues);
	}
}